package baidu.hudson.plugin.result.collector.utils;

import baidu.hudson.plugin.result.collector.ResultPublisher;
import hudson.model.AbstractBuild;
import hudson.model.Cause;
import hudson.model.Project;
import hudson.scm.SubversionChangeLogSet;
import hudson.triggers.SCMTrigger;
import hudson.triggers.TimerTrigger;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This is a class contain the factory method , which is used to parse the build information into different format
 * User: Richard
 * Date: 4/20/11
 * Time: 11:13 PM
 * To change this template use File | Settings | File Templates.
 */
public class BuildAnalyzer {
    private BuildAnalyzer() {

    }

    /**
     * generate a json key-value paires , which contain all the server needs values from the build result
     *
     * @param build     the build contain the result
     * @param publisher contain some build properties which we set in the golbal-config and job-config page
     * @return a json key-value paires , which contain all the server needs values from the build result
     */
    public static String generateMappedJsonResult(AbstractBuild build, ResultPublisher publisher) {
        Map<String, String> valuePairs = generateMappedResult(build, publisher);
        return JsonUtils.convertMapToJson(valuePairs);
    }

    /**
     * generate a map of key-value paires , which contain all the server needs values from the build result
     *
     * @param build     the build contain the result
     * @param publisher contain some build properties which we set in the golbal-config and job-config page
     * @return a json key-value paires , which contain all the server needs values from the build result
     */
    public static Map<String, String> generateMappedResult(AbstractBuild build, ResultPublisher publisher) {
        Map<String, String> valuePairs = new HashMap<String, String>();
        valuePairs.putAll(generateHudsonMap(build, publisher));
        //valuePairs.putAll(generateViewsMap(build,publisher));
        valuePairs.putAll(generateProjectMap(build, publisher));
        valuePairs.putAll(generateBuildMap(build, publisher));
        valuePairs = reorganizeMap(valuePairs, publisher);
        return valuePairs;
    }

    protected static Map<String, String> generateHudsonMap(AbstractBuild build, ResultPublisher publisher) {
        Map<String, String> valuePairs = new HashMap<String, String>();
        valuePairs.put("hudsonUrl", appendDomainForHudsonURL(publisher.getHudsonUrl()));
        valuePairs.put("teamFoundation", publisher.getTeamFoundation());
        //as the slave is too long , remove the slave
//        StringBuffer slaveStringBuffer = new StringBuffer();
//        for (int i = 0; i < Hudson.getInstance().getSlaves().size(); i++) {
//            slaveStringBuffer.append(Hudson.getInstance().getSlaves().get(i).getDisplayName());
//        }
//        valuePairs.put("hudsonSlave", slaveStringBuffer.toString());
        valuePairs.put("hudsonSlave", "");
        return valuePairs;

    }

    private static String appendDomainForHudsonURL(String url) {
        StringBuilder stringBuilder = new StringBuilder(url);
        if (url.contains(".baidu.com"))
            return url;
        else {
            Integer lastIndex = 0;
            Integer currentIndex = 0;
            Integer startIndex = 0;
            Pattern pattern = Pattern.compile("/");
            Matcher matcher = pattern.matcher(url);
            while (matcher.find()) {
                if (lastIndex == 0) {
                    lastIndex = matcher.start();
                }
                currentIndex = matcher.start();
                if ((currentIndex - lastIndex) > 1) {
                    startIndex = matcher.start();
                    if (stringBuilder.substring(lastIndex, matcher.start()).contains(":")) {
                        startIndex = stringBuilder.substring(lastIndex, matcher.start()).indexOf(":") + lastIndex;
                    }

                    return new StringBuffer(stringBuilder.substring(0, startIndex)).append(".baidu.com").append(stringBuilder.substring(startIndex, stringBuilder.length())).toString();
                }
                lastIndex = currentIndex;
            }
            return url;
        }
    }

    protected static Map<String, String> generateViewsMap(AbstractBuild build, ResultPublisher publisher) {
        Map<String, String> valuePairs = new HashMap<String, String>();
        valuePairs.put("icafeProject", publisher.getIcafeProject());  //
        valuePairs.put("icafeModule", publisher.getIcafeModule());
        valuePairs.put("icafeVersion", publisher.getIcafeVersion());
        valuePairs.put("viewUrl", publisher.getViewUrl());
        valuePairs.put("viewName", publisher.getViewName());
        return valuePairs;
    }

    protected static Map<String, String> generateProjectMap(AbstractBuild build, ResultPublisher publisher) {
        Map<String, String> valuePairs = new HashMap<String, String>();
        valuePairs.put("projectType", publisher.getProjectType());
        valuePairs.put("projectName", build.getProject().getName());

        valuePairs.put("child_projects", "");
        for (Object project : build.getProject().getDownstreamProjects()) {
            valuePairs.put("child_projects", valuePairs.get("child_projects") + ((Project) project).getDisplayName() + ";");
        }
//        if(valuePairs.get("child_projects").equals("")){
//            valuePairs.remove("child_projects");
//        }

        valuePairs.put("parent_projct", "");
        for (Object project : build.getProject().getUpstreamProjects()) {
            valuePairs.put("parent_projct", valuePairs.get("parent_projct") + ((Project) project).getDisplayName() + ";");
        }
//        if(valuePairs.get("parent_projct").equals("")){
//           valuePairs.remove("parent_projct");
//        }

        valuePairs.put("projectUrl", build.getProject().getUrl());
        return valuePairs;
    }

    protected static Map<String, String> generateBuildMap(AbstractBuild build, ResultPublisher publisher) {
        Map<String, String> valuePairs = new HashMap<String, String>();
        valuePairs.put("build_num", String.valueOf(build.getNumber()));
        SimpleDateFormat dataFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        valuePairs.put("build_data", dataFormat.format(build.getTimestamp().getTime()));
        valuePairs.put("cause_action_user", "");
        valuePairs.put("cause_action", "");

        //generate the cause action
        generateCauseActionStringInPriorityOrder(build, publisher, valuePairs);

        valuePairs.put("failCount", "0");
        valuePairs.put("skipCount", "0");
        valuePairs.put("totalCount", "0");
        if (build.getTestResultAction() != null) {
            valuePairs.put("failCount", String.valueOf(build.getTestResultAction().getFailCount()));
            valuePairs.put("skipCount", String.valueOf(build.getTestResultAction().getSkipCount()));
            valuePairs.put("totalCount", String.valueOf(build.getTestResultAction().getTotalCount()));
        }


        valuePairs.put("result", build.getResult().toString());
        if (build.getDuration() < 1L) {
            valuePairs.put("duration", String.valueOf(new GregorianCalendar().getTimeInMillis() - build.getTimeInMillis()));
        } else {
            valuePairs.put("duration", String.valueOf(build.getDuration()));
        }
        String buildOn = build.getBuiltOnStr();
        if (buildOn.equals("") || buildOn == null) {
            valuePairs.put("build_on", publisher.getLocalServername());
        } else {
            valuePairs.put("build_on", buildOn);
        }

        //as the slave is too long , remove the slave
//        StringBuffer slaveLabels = new StringBuffer();
//        slaveLabels.append("[");
//        for (TagCloud<LabelAtom>.Entry atom : build.getBuiltOn().getLabelCloud()) {
//            slaveLabels.append(atom.item.getName()).append(",");
//        }
//        int index = slaveLabels.lastIndexOf(",");
//        if (index != -1) {
//            slaveLabels.deleteCharAt(index);
//        }
//        slaveLabels.append("]");
//        valuePairs.put("slave", slaveLabels.toString());
        valuePairs.put("slave", "");
        return valuePairs;
    }

    private static void generateCauseActionStringInPriorityOrder(AbstractBuild build, ResultPublisher publisher, Map<String, String> valuePairs) {
        try {
            for (int i = 0; i < build.getCauses().size(); i++) {
                if (build.getCauses().get(i) instanceof SCMTrigger.SCMTriggerCause) {
                    for (SubversionChangeLogSet.LogEntry logEntry : ((SubversionChangeLogSet) build.getChangeSet()).getLogs())
                        valuePairs.put("cause_action_user", logEntry.getAuthor().getId() + ";");
                    valuePairs.put("cause_action", "SCMTriggerCause");
                    return;

                }
                if (build.getCauses().get(i) instanceof Cause.UpstreamCause) {
                    valuePairs.put("cause_UpstreamCause", ((Cause.UpstreamCause) build.getCauses().get(i)).getShortDescription());
                    Cause.UpstreamCause cause = (Cause.UpstreamCause) build.getCauses().get(i);
                    StringBuffer sb = new StringBuffer();
                    sb.append("UpstreamCause by \"").append(cause.getUpstreamProject()).append("\" #")
                            .append(String.valueOf(cause.getUpstreamBuild()));
                    valuePairs.put("cause_action", sb.toString());
                    return;
                }
                if (build.getCauses().get(i) instanceof Cause.UserCause) {
                    valuePairs.put("cause_action_user", ((Cause.UserCause) build.getCauses().get(i)).getUserName());
                    valuePairs.put("cause_action", "UserCause");
                    return;
                }

                if (build.getCauses().get(i) instanceof Cause.RemoteCause) {
                    valuePairs.put("cause_RemoteCause", ((Cause.RemoteCause) build.getCauses().get(i)).getShortDescription());
                    valuePairs.put("cause_action", "RemoteCause");
                    return;
                }

                if (build.getCauses().get(i) instanceof TimerTrigger.TimerTriggerCause) {
                    valuePairs.put("cause_action", "TimerTriggerCause");
                    return;
                }
            }
            if (valuePairs.get("cause_action").equals("")) {
                valuePairs.put("cause_action", "other");
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    protected static Map<String, String> reorganizeMap(Map<String, String> valuePairs, ResultPublisher publisher) {
        Set<String> keySet = new HashSet();
        for (String key : valuePairs.keySet()) {
            if (valuePairs.get(key) == null || valuePairs.get(key).equals("")) {
                keySet.add(key);
            }

        }


        //remove the null element
        for (String key : keySet)

        {
            valuePairs.remove(key);
        }

        //remove the end ';'
        for (String key : valuePairs.keySet()) {
            if (valuePairs.get(key).endsWith(";")) {
                StringBuffer sb = new StringBuffer(valuePairs.get(key));
                valuePairs.put(key, sb.deleteCharAt(sb.lastIndexOf(";")).toString());
            }
        }

        return valuePairs;
    }
}
